package com.xuexi.bootstrap.dbf;



import com.xuexi.bootstrap.javadbf.DBFException;
import com.xuexi.bootstrap.javadbf.DBFField;
import com.xuexi.bootstrap.javadbf.DBFWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.function.Function;

public abstract class DBFFactory<S> {
	private static Logger log = LoggerFactory.getLogger(DBFFactory.class);
	protected LinkedHashMap<DBFField, Function<S, ?>> structure;
	public DBFFactory() {
		structure = new LinkedHashMap<DBFField, Function<S, ?>>();
	}
	
	public void registerField(byte dataType, String name, int length, int decimalCount, Function<S, ?> pr) {
		DBFField field = new DBFField();
		field.setName(name);
		field.setDataType(dataType);
		field.setFieldLength(length);
		field.setDecimalCount(decimalCount);
		structure.put(field, pr);
	}
	protected abstract String getID(S s);
	public void processData(Collection<S> data, String encoding, OutputStream os) throws DBFException {
		DBFWriter writer = new DBFWriter();
		writer.setCharactersetName(encoding);
		writer.setFields(structure.keySet().toArray(new DBFField[structure.size()]));
		
		ArrayList<Object> record = new ArrayList<Object>(structure.keySet().size());
		for(S s : data) {
			record.clear();
			for(DBFField key : structure.keySet()) {
				Function<S, ?> prt = structure.get(key);
				Object property = prt.apply(s);
				if(property == null) {
					log.debug(String.format("Property \"%s\" of data record \"%s\" is null", key.getName(), this.getID(s)));
					record.add("");
					continue;
				}
				else{
					record.add(property);
				}
			}
			writer.addRecord(record.toArray(new Object[record.size()]));			
		}
		writer.write(os);
	}
	
}
